package com.benshou.bcss.common.db.mybatisplus.typehandler;

import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.benshou.bcss.common.j17common.annotation.NotNull;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Objects;

/**
 * 工厂类：获取基于 Jackson Json 的数据库数据对象 TypeHandler
 *
 * @author <a href="mailto:liuzhenbang@benshou.com">Liu Zhenbang</a>
 */
@RequiredArgsConstructor
public class JacksonJsonTypeHandlerFactory {

    /**
     * 对象映射实例
     */
    @NonNull
    private final ObjectMapper objectMapper;

    /**
     * 从 Class 构建 TypeHandler
     *
     * @param cls Class
     * @return TypeHandler
     * @param <T> 处理的对象的类型
     */
    public <T> AbstractJsonTypeHandler<T> fromCls(@NonNull Class<T> cls) {
        return new AbstractJacksonJsonTypeHandler<>(cls) {
            @Override
            protected T _parse(@NotNull String json) throws JsonProcessingException {
                return objectMapper.readValue(json, cls);
            }
        };
    }

    /**
     * 从 TypeReference 构建 TypeHandler
     *
     * @param typeReference TypeReference
     * @return TypeHandler
     * @param <T> 处理的对象的类型
     */
    public <T> AbstractJsonTypeHandler<T> fromTypeReference(@NonNull TypeReference<T> typeReference) {
        return new AbstractJacksonJsonTypeHandler<>(getRawCls(typeReference.getType())) {
            @Override
            protected T _parse(@NotNull String json) throws JsonProcessingException {
                return objectMapper.readValue(json, typeReference);
            }
        };
    }

    /**
     * 从 Type 中获取 Class
     *
     * @param type Type
     * @return Class
     */
    private Class<?> getRawCls(@NotNull Type type) {
        if (type instanceof Class<?> cls) {
            return cls;
        }

        if (type instanceof ParameterizedType parameterizedType) {
            return getRawCls(parameterizedType.getRawType());
        }

        // 从 Jackson Type Factory 中获取
        return Objects.requireNonNull(this.objectMapper.getTypeFactory().constructType(type).getRawClass());
    }

    /**
     * TypeHandler: 基于 Jackson Json
     *
     * @param <T> 处理的对象的类型
     */
    private abstract class AbstractJacksonJsonTypeHandler<T> extends AbstractJsonTypeHandler<T> {

        AbstractJacksonJsonTypeHandler(@NotNull Class<?> type) {
            super(type);
        }

        /**
         * 解析 Json
         *
         * @param json Json 字符串
         * @return 解析出的对象
         * @throws JsonProcessingException 解析出错时，抛出此异常
         */
        protected abstract T _parse(@NotNull String json) throws JsonProcessingException;

        @SneakyThrows(JsonProcessingException.class)
        @Override
        public T parse(String json) {
            return json == null ? null : _parse(json);
        }

        @SneakyThrows(JsonProcessingException.class)
        @Override
        public String toJson(T obj) {
            return obj == null ? null : objectMapper.writeValueAsString(obj);
        }
    }
}
